#pragma ident "$Id XY. CAO 2016-11-16 $"

/**
* @file SimpleFilter.cpp
* This class filters out satellites with observations grossly out of bounds.
*/

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
//
//  Dagoberto Salazar - gAGE ( http://www.gage.es ). 2007, 2008, 2011
//
//============================================================================


#include "SimpleFilter.hpp"


namespace gpstk
{

   // Returns a string identifying this object.
   std::string SimpleFilter::getClassName() const
   { return "SimpleFilter"; }


   // Returns a satTypeValueMap object, filtering the target observables.
   //
   // @param gData     Data object holding the data.
   //
   satTypeValueMap& SimpleFilter::Process(satTypeValueMap& gData)
      noexcept(false)
   {

       try
       {
           // Now, Let's check the range of the code observables.
           // if not located in the given range, the satellite
           // will be removed directly.

           SatIDSet satRejectedSet;

           double defaultMaxLimit = maxLimit;

           TypeIDSet tempFilterTypeSet;

           // Loop through all the satellites
           for ( satTypeValueMap::iterator satIt = gData.begin();
                 satIt != gData.end();
                 ++satIt )
           {
              // get the satellite  identify
              SatID::SatelliteSystem sys = (*satIt).first.system;

              if( sys == SatelliteSystem::GPS )
              {
                  tempFilterTypeSet = filterTypeSet;
              }
              else if( sys == SatelliteSystem::GLONASS )
              {
                  tempFilterTypeSet = GLOFilterTypeSet;
              }
              else if( sys == SatelliteSystem::Galileo )
              {
                  tempFilterTypeSet = GALFilterTypeSet;
              }
              else if( sys == SatelliteSystem::BDS )
              {
                  tempFilterTypeSet = BDSFilterTypeSet;
              }
              else
              {
                  continue;
              }


              // Check all the indicated TypeID's
              TypeIDSet::const_iterator pos;
              for (pos = tempFilterTypeSet.begin(); pos != tempFilterTypeSet.end(); ++pos)
              {
                  double value(0.0);

                  // Try to extract the values
                  if((*satIt).second.find(*pos) != (*satIt).second.end())
                  {
                      value = (*satIt).second[(*pos)];

                      // Now, check that the value is within bounds
                      if ( !( checkValue(value) ) )
                      {
                          (*satIt).second.removeTypeID((*pos));
                      }
                  }

              }// end type loop

              setMaxLimit(defaultMaxLimit);

           }// end satellite loop

//  stdut <tClassName() << " RejectedSatNum: " << satRejectedSet.  size() << std::endl;
//  stdut <tClassName() << " CurrentSatNum: " << gData.numSats()   << std::endl;

//         cout << satRejectedSet.size() << endl;

           gData.removeSatID(satRejectedSet);

           return gData;

       }
       catch(SVNumException& s)
       {
               // Rethrow the SVNumException
               GPSTK_RETHROW(s);
       }
       catch(Exception& u)
       {
               // Throw an exception if something unexpected happens
               ProcessingException e( getClassName() + ":"
                       + u.what() );

               GPSTK_THROW(e);

       }


   }  // End of 'SimpleFilter::Process()'


    /** Return a sourceRinex object, adding the new data generated when
     *  calling a modeling object.
     *
     * @param gData    Data object holding the data.
     */
   void SimpleFilter::Process(commonHeader& comHeader,sourceRinex& gData)
       noexcept(false)
   {
       for(sourceDataMap::iterator sdmIt = gData.body.begin();
           sdmIt != gData.body.end();
           ++sdmIt)
       {
           Process( sdmIt->second );
       }

   }  // End of method 'SimpleFilter::Process()'

} // End of namespace gpstk
